#ifndef WRAPPERPTR_H
#define WRAPPERPTR_H

namespace CExpression
{
template <typename T> class WrapperPtr
{
public:
	static WrapperPtr<T> NULL_PTR;
	WrapperPtr<T>():ptr(0){}
	WrapperPtr<T>(T *p):ptr(p){}
	WrapperPtr<T>(const WrapperPtr<T> &p):ptr(const_cast< WrapperPtr<T>& >(p).Release()){}
	WrapperPtr<T>& operator=(const WrapperPtr<T>& p)
	{
		this->Free();
		this->ptr=const_cast< WrapperPtr<T>& >(p).Release();
		return *this;
	}
	~WrapperPtr()
	{
		this->Free();
	}
	T& operator*()
	{
		return *(this->ptr);
	}
	const T& operator*() const
	{
		return *(this->ptr);
	}
	T* operator->()
	{
		return this->ptr;
	}
	const T* operator->() const
	{
		return this->ptr;
	}
	bool operator==(const WrapperPtr<T> &rhs) const
	{
		return this->Get()==rhs.Get();
	}
	bool operator!=(const WrapperPtr<T> &rhs) const
	{
		return !this->operator==(rhs);
	}
	T* Get()
	{
		return this->ptr;
	}
	const T* Get() const
	{
		return this->ptr;
	}
	T* Release()
	{
		T *temp=this->ptr;
		this->ptr=0;
		return temp;
	}
private:
	void Free()
	{
		delete this->ptr;
	}
	T *ptr;
};

template <typename T> WrapperPtr<T> WrapperPtr<T>::NULL_PTR;
}

#endif